<?php

namespace common\service;

use common\exception\LogicException;
use common\model\TenantAuthenticationModel;
use common\model\TenantGroupApplyModel;
use common\model\TenantGroupMemberModel;
use common\model\TenantGroupModel;
use common\model\TenantModel;
use common\model\TenantStepCategoryLevelModel;
use support\ErrorCode;
use think\Exception;

class TenantGroupApplyService
{
    protected $tenantGroupApplyModel;

    public function __construct()
    {
        $this->tenantGroupApplyModel = model(TenantGroupApplyModel::class);
    }

    /**
     * 查询申请列表
     * @param $param
     * @param $tenantId
     * @return array
     * @throws \Exception
     */
    public function select($param, $tenantId)
    {
        $options = $param['param'];
        $tenantStepCateGoryLevelData = [];
        $tenantGroupData = model(TenantGroupModel::class)->find($options['filter']['tenant_group_id']);
        if ($tenantGroupData['tenant_id'] != $tenantId) {
            throw_strack_exception("Tenant Not Permission", ErrorCode::TENANT_NOT_PERMISSION);
        }
        $tenantGroupApplyList = $this->tenantGroupApplyModel
            ->field('tenant_group_apply.*,tenant_group.name as apply_tenant_group_name')
            ->join('tenant_group on tenant_group_apply.tenant_group_id = tenant_group.id')
            ->where($options['filter'])
            ->page(...$options['page'])
            ->select();
        if (empty($tenantGroupApplyList)) {
            return [];
        }
        $tenantIds = array_column($tenantGroupApplyList, 'tenant_id');
        $tenantAuthenticationModel = model(TenantAuthenticationModel::class);
        $tenantAuthenticationList = $tenantAuthenticationModel->where(['tenant_id' => ['IN', implode(',', $tenantIds)]])->select();
        $tenantAuthenticationMap = array_column($tenantAuthenticationList, null, 'tenant_id');
        $tenantGroupApplyMap = array_column($tenantGroupApplyList, null, 'tenant_id');
        $tenantModel = model(TenantModel::class);
        $tenantOptions = [
            "fields" => 'tenant.id,tenant.name,tenant.status,tenant.created',
            'filter' => [
                'tenant.id' => ['IN', implode(',', $tenantIds)],
                'tenant.status' => 'active'
            ],
        ];
        $tenantList = $tenantModel->selectData($tenantOptions);
        if (empty($tenantList)) {
            throw_strack_exception('Tenant Not Found', ErrorCode::TENANT_NOT_EXIST);
        }
        // 每个公司对应不同分类的等级数据
        $tenantStepCateGoryLevelModel = model(TenantStepCategoryLevelModel::class);
        $tenantStepCateGoryLevelList = $tenantStepCateGoryLevelModel
            ->field("uuid,created,updated,created_by", true)
            ->where(['tenant_id' => ['In', implode(',', $tenantIds)]])
            ->select();
        if (!empty($tenantStepCateGoryLevelList)) {
            $tenantStepCateGoryLevelData = array_group_by($tenantStepCateGoryLevelList, 'tenant_id');
        }
        $tenantData = [];
        foreach ($tenantList['rows'] as $item) {
            $item['tenant']['apply_id'] = $tenantGroupApplyMap[$item['tenant']['id']]['id'];
            $item['tenant']['level_data'] = $tenantStepCateGoryLevelData[$item['tenant']['id']] ?? [];
            $item['tenant']['apply_status'] = $tenantGroupApplyMap[$item['tenant']['id']]['status'];
            $item['tenant']['apply_tenant_group_name'] = $tenantGroupApplyMap[$item['tenant']['id']]['apply_tenant_group_name'];
            $item['tenant']['legal_person_name'] = $tenantAuthenticationMap[$item['tenant']['id']]['legal_person_name'];
            $tenantData[] = $item['tenant'];
        }
        return $tenantData;
    }

    /**
     * 发起申请
     * @param $data
     * @param $userId
     * @param $tenantId
     * @return array|bool
     * @throws \Exception
     */
    public function sendApply($data, $userId, $tenantId)
    {
        $tenantAuthModel = model(TenantAuthenticationModel::class);
        $tenantGroupApplyExist = $this->tenantGroupApplyModel->where(['tenant_group_id' => $data['tenant_group_id'], 'tenant_id' => $tenantId])->find();
        if ($tenantGroupApplyExist) {
            $tenantGroupMemberExist = model(TenantGroupMemberModel::class)->where(['tenant_group_id' => $data['tenant_group_id'], 'tenant_id' => $tenantId])->find();
            // 申请中或者已同意过且还在成员列表里的请求不能重复发起申请
            if ($tenantGroupApplyExist['status'] == 'applying') {
                throw_strack_exception('Apply Already Exists', ErrorCode::TENANT_GROUP_APPLY_EXISTS);
            } else if ($tenantGroupApplyExist['status'] == 'agree' && $tenantGroupMemberExist) {
                throw_strack_exception('Tenant Apply Status Already Changed', ErrorCode::TENANT_GROUP_APPLY_STATUS);
            } else if ($tenantGroupApplyExist['status'] == 'refuse' || empty($tenantGroupMemberExist)) {
                $tenantGroupApplyData = $tenantGroupApplyExist;
                $tenantGroupApplyData['status'] = 'applying';
                $tenantGroupApplyData['apply_user_id'] = $userId;
                return $this->tenantGroupApplyModel->save($tenantGroupApplyData);
            }
        } else {
            $tenantAuth = $tenantAuthModel->where(['tenant_id' => $tenantId])->find();
            if (empty($tenantAuth) || $tenantAuth['status'] != "active") {
                throw_strack_exception('Tenant Not Auth', ErrorCode::TENANT_AUTHENTICATION_FAILED);
            }
            // 当前公司必须是认证的才能申请
            $tenantGroupModel = model(TenantGroupModel::class);
            $tenantGroupExist = $tenantGroupModel->find($data['tenant_group_id']);
            if (empty($tenantGroupExist)) {
                throw_strack_exception('TenantGroup Not Exists', ErrorCode::TENANT_GROUP_NOT_EXIST);
            }
            $tenantGroupMemberModel = model(TenantGroupMemberModel::class);
            $tenantGroupMemberFilter = [
                'tenant_id' => $tenantId,
                'tenant_group_id' => $data['tenant_group_id']
            ];
            $tenantGroupMemberExist = $tenantGroupMemberModel->where($tenantGroupMemberFilter)->find();
            // 避免重复添加成员
            if ($tenantGroupMemberExist) {
                throw_strack_exception('Member Already Exists', ErrorCode::TENANT_MEMBER_EXISTS);
            }
            $data['tenant_id'] = $tenantId;
            $data['apply_user_id'] = $userId;
            return $this->tenantGroupApplyModel->addItem($data);
        }
    }

    /**
     * 审核申请
     * @param $data
     * @param $userId
     * @return bool
     * @throws \Throwable
     */
    public function auditApply($data, $userId)
    {
        $tenantGroupApplyData = $this->tenantGroupApplyModel->find($data['id']);
        if (empty($tenantGroupApplyData)) {
            throw_strack_exception('Apply Not Exist', ErrorCode::TENANT_GROUP_APPLY_NOT_EXIST);
        }
        if ($tenantGroupApplyData['status'] != 'applying') {
            throw_strack_exception('Apply Status Changed', ErrorCode::TENANT_GROUP_APPLY_STATUS_CHANGED);
        }
        $data['audit_user_id'] = $userId;
        $data['updated'] = time();
        $this->tenantGroupApplyModel->startTrans();
        try {
            $this->tenantGroupApplyModel->save($data);
            if ($data['status'] == 'agree') {
                // 如果同意就将公司加入进成员中
                $tenantGroupMemberModel = model(TenantGroupMemberModel::class);
                $tenantGroupMemberFilter = [
                    'tenant_id' => $tenantGroupApplyData['tenant_id'],
                    'tenant_group_id' => $tenantGroupApplyData['tenant_group_id']
                ];
                $tenantGroupMemberExist = $tenantGroupMemberModel->where($tenantGroupMemberFilter)->find();
                if ($tenantGroupMemberExist) {
                    throw new LogicException('Member Already Exists', ErrorCode::TENANT_MEMBER_EXISTS);
                }
                $tenantGroupMemberData['tenant_id'] = $tenantGroupApplyData['tenant_id'];
                $tenantGroupMemberData['tenant_group_id'] = $tenantGroupApplyData['tenant_group_id'];
                $tenantGroupMemberData['created_by'] = $userId;
                $tenantGroupMemberModel->addItem($tenantGroupMemberData);
            }
            return $this->tenantGroupApplyModel->commit();
        } catch (\Throwable $e) {
            $this->tenantGroupApplyModel->rollback();
            throw $e;
        }
    }

    /**
     * 当前租户查找申请集团
     * @param $tenantId
     * @return array|false|mixed|string
     */
    public function selectCurrentTenant($tenantId)
    {
        $tenantGroupApplyList = $this->tenantGroupApplyModel->where(['tenant_id' => $tenantId])->select();
        if (empty($tenantGroupApplyList)) {
            return [];
        }
        $tenantGroupApplyMap = array_column($tenantGroupApplyList, null, 'tenant_group_id');
        $tenantGroupIds = array_column($tenantGroupApplyList, 'tenant_group_id');
        $tenantGroupModel = model(TenantGroupModel::class);
        $tenantGroupList = $tenantGroupModel->where(['id' => ['IN', implode(',', $tenantGroupIds)]])->select();
        $tenantIds = array_column($tenantGroupList, 'tenant_id');
        // 查找这些集团的拥有者
        $tenantModel = model(TenantModel::class);
        $tenantList = $tenantModel->where(['id' => ['IN', implode(',', $tenantIds)]])->select();
        $tenantMap = array_column($tenantList, null, 'id');
        foreach ($tenantGroupList as &$item) {
            $item['owner'] = $tenantMap[$item['tenant_id']]['name'] ?? "";
            $item['apply_status'] = $tenantGroupApplyMap[$item['id']]['status'] ?? "";
        }
        return $tenantGroupList;
    }

    /**
     * 重新激活申请状态
     * @param $data
     * @param $userId
     * @return bool|float|int|string
     * @throws \Exception
     */
    public function activate($data, $userId)
    {
        $tenantGroupApplyData = $this->tenantGroupApplyModel->find($data['id']);
        if (empty($tenantGroupApplyData)) {
            throw_strack_exception('Apply Not Exist', ErrorCode::TENANT_GROUP_APPLY_NOT_EXIST);
        }
        if ($tenantGroupApplyData['status'] != "refuse") {
            throw_strack_exception("Tenant Apply Status Already Changed", ErrorCode::TENANT_GROUP_APPLY_STATUS);
        }
        $tenantGroupApplyData['status'] = $data['status'];
        $tenantGroupApplyData['apply_user_id'] = $userId;
        return $this->tenantGroupApplyModel->save($tenantGroupApplyData);
    }
}